/*******************************************************************************
** 文件名称：button.c
** 文件作用：按键
** 编写作者：Tom Free 付瑞彪
** 编写时间：2021-05-30
** 文件备注：
** 更新记录：
**           2021-05-30 -> 创建文件
**                                                            <Tom Free 付瑞彪>
**
**           Copyright (c) 2018-2021 付瑞彪 All Rights Reserved
**
**       1 Tab == 4 Spaces     UTF-8     ANSI C Language(C99)
*******************************************************************************/

#include "button.h"
#include "chip_delay.h"

/* 按键状态 */
typedef enum
{
    BTN_STATUS_RELEASE,                 /* 释放态 */
    BTN_STATUS_LONG_PRESS_CONFIRM,      /* 长按确认状态 */
    BTN_STATUS_LONG_PRESS_REPEAT,       /* 长按重复状态 */
} btn_status_t;

/* 按键参数结构 */
typedef struct
{
    uint8_t      level;
    btn_status_t status[BTN_ID_MAX];
    uint8_t      cnt[BTN_ID_MAX];
    uint8_t      deb_cnt[BTN_ID_MAX];
    btn_event_t  evt[BTN_ID_MAX];
} btn_args_t;

/* 按键参数 */
static btn_args_t btn_args;

/* 初始化 */
void button_init(void)
{
    /* PB0/1/2 */
    DDRB &= ~0x07;  /* 输入 */
    PORTB |= 0x07;  /* 上拉 */

    delay_us(10);

    btn_args.level = PINB & 0x07;
    for (btn_id_t i = BTN_ID_MODE; i < BTN_ID_MAX; i++)
    {
        btn_args.status[i] = BTN_STATUS_RELEASE;
        btn_args.cnt[i] = 0;
        btn_args.deb_cnt[i] = 0;
    }
}

/* 按键轮询，10ms轮一次，返回值采用位定义，一位表示当前按键是否有事件产生 */
uint8_t button_poll(void)
{
    uint8_t res = 0x00;
    uint8_t tmp;
    uint8_t level = PINB & 0X07;

    for (btn_id_t i = BTN_ID_MODE; i < BTN_ID_MAX; i++)
    {
        tmp = level & (1 << i);
        if (!(tmp ^ btn_args.level))
        {
            btn_args.deb_cnt[i] = 0;
            continue;
        }
        else if (++btn_args.deb_cnt[i] < 2)
        {
            continue;
        }

        switch (btn_args.status[i])
        {
        case BTN_STATUS_RELEASE:
            if (!tmp)
            {
                btn_args.status[i] = BTN_STATUS_LONG_PRESS_CONFIRM;
                btn_args.cnt[i] = 0;
            }
            break;

        case BTN_STATUS_LONG_PRESS_CONFIRM:
            if (tmp)
            {
                btn_args.status[i] = BTN_STATUS_RELEASE;
                btn_args.cnt[i] = 0;
                btn_args.evt[i] = BTN_EVENT_CLICK;
                res |= (1 << i);
            }
            else if (++btn_args.cnt[i] >= 100)
            {
                btn_args.status[i] = BTN_STATUS_LONG_PRESS_REPEAT;
                btn_args.cnt[i] = 0;
                btn_args.evt[i] = BTN_EVENT_LONG_PRESS;
                res |= (1 << i);
            }
            break;

        case BTN_STATUS_LONG_PRESS_REPEAT:
            if (tmp)
            {
                btn_args.status[i] = BTN_STATUS_RELEASE;
                btn_args.cnt[i] = 0;
            }
            else if (++btn_args.cnt[i] >= 10)
            {
                btn_args.cnt[i] = 0;
                btn_args.evt[i] = BTN_EVENT_LONG_REPEAT;
                res |= (1 << i);
            }
            break;

        default:
            break;
        }
    }

    return res;
}

/* 获取按键事件 */
btn_event_t button_get_event(btn_id_t btn_id)
{
    return btn_args.evt[btn_id];
}
